﻿/*  (c) 2008 Benjamin Schroeter
 *  You are allowed to use this code in all your commercial, non-commercial, open and closed source projects.
 *  But you have to leave this Copyright message in all files. This code is provided "as is" without warranty of any kind.
 *  If you have any enhancements or bug reports I will appreciate a short feedback.
 *  For more information visit the article to this code on my blog at 
 *  http://www.ticklishtechs.net/2008/04/12/to-restrict-dynamically-the-usage-of-domain-properties-in-dsl-models/ */
 
using System;
using System.ComponentModel;

namespace BenjaminSchroeter.Dsl.UserRestrictions
{
    /// <summary>
    /// A PropertyDescriptor for read-only properties.
    /// 
    /// This PropertyDescriptor wrappes another PropertyDescriptor and delegates
    /// all calls to this one. Only the IsReadOnly property will return always true.
    /// </summary>
    public class ReadOnlyPropertyDescriptor : PropertyDescriptor
    {
        private readonly PropertyDescriptor descriptor;

        /// <summary>
        /// Initializes a new instance of the <see cref="ReadOnlyPropertyDescriptor"/> class.
        /// </summary>
        /// <param name="descriptor">A base descriptor for this descriptor.</param>
        public ReadOnlyPropertyDescriptor(PropertyDescriptor descriptor) : base(descriptor.Name, new Attribute[] {})
        {
            this.descriptor = descriptor;
        }
        
        /// <summary>
        /// Indicates that this property is allways read only
        /// </summary>
        /// <remarks>For writable properties this ReadOnlyPropertyDescriptor must not be used.</remarks>
        public override bool IsReadOnly
        {
            get { return true; }
        }

        #region delegate all memeber to default descriptor
        /// <summary>
        /// Enables other objects to be notified when this property changes.
        /// </summary>
        /// <param name="component">The component to add the handler for.</param>
        /// <param name="handler">The delegate to add as a listener.</param>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="component"/> or <paramref name="handler"/> is null.</exception>
        public new void AddValueChanged(object component, EventHandler handler)
        {
            descriptor.AddValueChanged(component, handler);
        }

        /// <summary>
        /// When overridden in a derived class, returns whether resetting an object changes its value.
        /// </summary>
        /// <param name="component">The component to test for reset capability.</param>
        /// <returns>
        /// true if resetting the component changes its value; otherwise, false.
        /// </returns>
        public override bool CanResetValue(object component)
        {
            return descriptor.CanResetValue(component);
        }

        /// <summary>
        /// When overridden in a derived class, gets the type of the component this property is bound to.
        /// </summary>
        /// <value></value>
        /// <returns>A <see cref="T:System.Type"/> that represents the type of component this property is bound to. When the <see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)"/> or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)"/> methods are invoked, the object specified might be an instance of this type.</returns>
        public override Type ComponentType
        {
            get { return descriptor.ComponentType; }
        }

        /// <summary>
        /// Gets the type converter for this property.
        /// </summary>
        /// <value></value>
        /// <returns>A <see cref="T:System.ComponentModel.TypeConverter"/> that is used to convert the <see cref="T:System.Type"/> of this property.</returns>
        /// <PermissionSet>
        /// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode"/>
        /// </PermissionSet>
        public new TypeConverter Converter
        {
            get { return descriptor.Converter; }
        }

        /// <summary>
        /// Compares this to another object to see if they are equivalent.
        /// </summary>
        /// <param name="obj">The object to compare to this <see cref="T:System.ComponentModel.PropertyDescriptor"/>.</param>
        /// <returns>
        /// true if the values are equivalent; otherwise, false.
        /// </returns>
        public new bool Equals(object obj)
        {
            return descriptor.Equals(obj);
        }

        /// <summary>
        /// Returns the default <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/>.
        /// </returns>
        /// <PermissionSet>
        /// 	<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence"/>
        /// </PermissionSet>
        public new PropertyDescriptorCollection GetChildProperties()
        {
            return descriptor.GetChildProperties();
        }

        /// <summary>
        /// Returns a <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> for a given object using a specified array of attributes as a filter.
        /// </summary>
        /// <param name="instance">A component to get the properties for.</param>
        /// <param name="filter">An array of type <see cref="T:System.Attribute"/> to use as a filter.</param>
        /// <returns>
        /// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> with the properties that match the specified attributes for the specified component.
        /// </returns>
        public new PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter)
        {
            return descriptor.GetChildProperties(instance, filter);
        }

        /// <summary>
        /// Returns a <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> using a specified array of attributes as a filter.
        /// </summary>
        /// <param name="filter">An array of type <see cref="T:System.Attribute"/> to use as a filter.</param>
        /// <returns>
        /// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> with the properties that match the specified attributes.
        /// </returns>
        public new PropertyDescriptorCollection GetChildProperties(Attribute[] filter)
        {
            return descriptor.GetChildProperties(filter);
        }

        /// <summary>
        /// Returns a <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> for a given object.
        /// </summary>
        /// <param name="instance">A component to get the properties for.</param>
        /// <returns>
        /// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> with the properties for the specified component.
        /// </returns>
        public new PropertyDescriptorCollection GetChildProperties(object instance)
        {
            return descriptor.GetChildProperties(instance);
        }

        /// <summary>
        /// Gets an editor of the specified type.
        /// </summary>
        /// <param name="editorBaseType">The base type of editor, which is used to differentiate between multiple editors that a property supports.</param>
        /// <returns>
        /// An instance of the requested editor type, or null if an editor cannot be found.
        /// </returns>
        public new object GetEditor(Type editorBaseType)
        {
            return descriptor.GetEditor(editorBaseType);
        }

        /// <summary>
        /// Returns the hash code for this object.
        /// </summary>
        /// <returns>The hash code for this object.</returns>
        public new int GetHashCode()
        {
            return descriptor.GetHashCode();
        }

        /// <summary>
        /// When overridden in a derived class, gets the current value of the property on a component.
        /// </summary>
        /// <param name="component">The component with the property for which to retrieve the value.</param>
        /// <returns>
        /// The value of a property for a given component.
        /// </returns>
        public override object GetValue(object component)
        {
            return descriptor.GetValue(component);
        }

        /// <summary>
        /// Gets a value indicating whether this property should be localized, as specified in the <see cref="T:System.ComponentModel.LocalizableAttribute"/>.
        /// </summary>
        /// <value></value>
        /// <returns>true if the member is marked with the <see cref="T:System.ComponentModel.LocalizableAttribute"/> set to true; otherwise, false.</returns>
        public new bool IsLocalizable
        {
            get { return descriptor.IsLocalizable; }
        }

        /// <summary>
        /// When overridden in a derived class, gets the type of the property.
        /// </summary>
        /// <value></value>
        /// <returns>A <see cref="T:System.Type"/> that represents the type of the property.</returns>
        public override Type PropertyType
        {
            get { return descriptor.PropertyType; }
        }

        /// <summary>
        /// Enables other objects to be notified when this property changes.
        /// </summary>
        /// <param name="component">The component to remove the handler for.</param>
        /// <param name="handler">The delegate to remove as a listener.</param>
        /// <exception cref="T:System.ArgumentNullException">
        /// 	<paramref name="component"/> or <paramref name="handler"/> is null.</exception>
        public new void RemoveValueChanged(object component, EventHandler handler)
        {
            descriptor.RemoveValueChanged(component, handler);
        }

        /// <summary>
        /// When overridden in a derived class, resets the value for this property of the component to the default value.
        /// </summary>
        /// <param name="component">The component with the property value that is to be reset to the default value.</param>
        public override void ResetValue(object component)
        {
            descriptor.ResetValue(component);
        }

        /// <summary>
        /// Gets a value indicating whether this property should be serialized, as specified in the <see cref="T:System.ComponentModel.DesignerSerializationVisibilityAttribute"/>.
        /// </summary>
        /// <value></value>
        /// <returns>One of the <see cref="T:System.ComponentModel.DesignerSerializationVisibility"/> enumeration values that specifies whether this property should be serialized.</returns>
        public new DesignerSerializationVisibility SerializationVisibility
        {
            get { return descriptor.SerializationVisibility; }
        }

        /// <summary>
        /// When overridden in a derived class, sets the value of the component to a different value.
        /// </summary>
        /// <param name="component">The component with the property value that is to be set.</param>
        /// <param name="value">The new value.</param>
        public override void SetValue(object component, object value)
        {
            descriptor.SetValue(component, value);
        }

        /// <summary>
        /// When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
        /// </summary>
        /// <param name="component">The component with the property to be examined for persistence.</param>
        /// <returns>
        /// true if the property should be persisted; otherwise, false.
        /// </returns>
        public override bool ShouldSerializeValue(object component)
        {
            return descriptor.ShouldSerializeValue(component);
        }

        /// <summary>
        /// Gets a value indicating whether value change notifications for this property may originate from outside the property descriptor.
        /// </summary>
        /// <value></value>
        /// <returns>true if value change notifications may originate from outside the property descriptor; otherwise, false.</returns>
        public new bool SupportsChangeEvents
        {
            get { return descriptor.SupportsChangeEvents; }
        }
        #endregion
    }
}
